/**
 * @file PCR.h
 *
 * This file defines the PCR base calculation.
 *
 * The PCR value is decomposed into two fields: an 9 bits extension field iPCReasing at 27MHz and wrapping every 300 unit, and
 * a 33 bits base field increasing at 27MHz / 300 = 90 kHz.
 * This file proposes also the PCR value in 64 bits at 27 MHz called PCR64, and in 32 bits at 45kHz called PCR32.
 *
 * @author Luc Fourestier
 * @date 2009
 */

#ifndef PCR_H_
#define PCR_H_

// PCR attributes
#define PCR_EXT_FREQ_MHZ (27)		//!< The extension field frequency in MHz
#define PCR_EXT_FREQ_KHZ (1000 * PCR_EXT_FREQ_MHZ)	//!< The extension field frequency in kHz
#define PCR_EXT_FREQ_HZ (1000 * PCR_EXT_FREQ_KHZ)	//!< The extension field frequency in Hz
#define PCR_BASE_FREQ_KHZ (90) 		//!< The base field frequency in kHz
#define PCR_BASE_FREQ_HZ (1000 * PCR_BASE_FREQ_KHZ)    //!< The base field frequency in Hz

#define PCR_EXT_WRAP (300)		//!< The extension field wrap value
#define PCR_BASE_WRAP (1LL<<33)	//!< The 33 bits base field wrap value
#define PCR64_WRAP (PCR_BASE_WRAP * PCR_EXT_WRAP)	//!< The 64 bits wrap value

#define PCR_PCR32_FREQ_KHZ (45) //!< PCR_BASE_FREQ_KHZ / 2


// Conversion macros
#define PCR_TO_PCR32(base) ((unsigned long)(base >> 1))   //!< Converts PCR into PCR 32 bits.
#define PCR32_TO_PCR_BASE(x) ((unsigned long long)x << 1) //!< Converts PCR 32 bits into PCR.

#define PCR_TO_PCR64(base, ext) ((unsigned long long)((base * PCR_EXT_WRAP) + (unsigned long long)ext)) //!< Converts PCR into PCR 64 bits.
#define PCR64_TO_PCR_BASE(x) ((unsigned long long)((x / PCR_EXT_WRAP) % PCR_BASE_WRAP)) 	//!< Converts PCR 64 bits into PCR base.
#define PCR64_TO_PCR_EXT(x) ((unsigned short)(x % PCR_EXT_WRAP)) 		//!< Converts PCR 64 bits into PCR ext.

#define PCR64_TO_PCR32(x) ((unsigned long)(x / 600)) 	   	  //!< Converts PCR64 into PCR32.
#define PCR32_TO_PCR64(x) (((unsigned long long) x ) * 600LL) //!< Converts PCR32 into PCR64.

#define PCR32_TO_MS(x) (x / PCR_PCR32_FREQ_KHZ)			//!< Converts PCR 32 bits into ms.
#define MS_TO_PCR32(x) (x * PCR_PCR32_FREQ_KHZ)			//!< Converts ms into PCR 32 bits.

#define PCR64_TO_MS(x) (x / PCR_EXT_FREQ_KHZ)			//!< Converts PCR 64 bits into ms.
#define MS_TO_PCR64(x) (x * PCR_EXT_FREQ_KHZ)			//!< Converts ms into PCR 64 bits.

#define PCR64_TO_S(x) (x / PCR_EXT_FREQ_HZ)			//!< Converts PCR 64 bits into s.
#define S_TO_PCR64(x) (x * PCR_EXT_FREQ_HZ)			//!< Converts s into PCR 64 bits.

#define PCR64_TO_US(x) (x / PCR_EXT_FREQ_MHZ)			//!< Converts PCR 64 bits into us.
#define US_TO_PCR64(x) (x * PCR_EXT_FREQ_MHZ)			//!< Converts us into PCR 64 bits.

#define PCR64_TO_NS(x) (x * 1000 / PCR_EXT_FREQ_MHZ)			//!< Converts PCR 64 bits into ns.
#define NS_TO_PCR64(x) (x * PCR_EXT_FREQ_MHZ / 1000)			//!< Converts ns into PCR 64 bits.

#endif /* PCR_H_ */
